/*
 * Main thread for the application 
*/

package com.costeaalex.blueserver.threads;

//import java.util.Map;
//import java.util.Set;

//import java.util.Map;
//import java.util.Set;

//import java.util.Map;
//import java.util.Set;

import javax.comm.CommPort;
import javax.comm.CommPortIdentifier;
import javax.comm.NoSuchPortException;
import javax.comm.PortInUseException;

import com.costeaalex.blueserver.communication.CommunicationManager;
import com.costeaalex.blueserver.interfaces.MainFrame;
import com.costeaalex.blueserver.server.BlueServerMonitor;
import com.costeaalex.blueserver.server.BlueServerClientStatus;
import com.costeaalex.blueserver.server.BlueServerReceiver;
import com.costeaalex.blueserver.settings.AppSettingsGet;
import com.costeaalex.blueserver.settings.Settings;
import com.costeaalex.blueserver.setup.SetupServerApp;
import com.costeaalex.blueserver.systemtray.SystemTrayManager;
import com.costeaalex.blueserver.timeout.HandleTimeoutProcess;
import com.costeaalex.blueserver.timeout.TimeoutProcess;

public class MainThread extends Thread
	{
	
	private AppSettingsGet aSG;
	private Settings set;
	private CommunicationManager cML;
	private StartBlueCoveServer sBCS;
	private StartCOMServer sCS;
	private HandleTimeoutProcess oTCP;
	private HandleTimeoutProcess oTBC;
	private CommPort cPL;
	private int serverRunning=0;
	private SystemTrayManager sT=null;
	private BlueServerReceiver serverR;
	private BlueServerClientStatus status;
	private BlueServerMonitor bSM;
	private SetupServerApp sS;
	
	public MainFrame mF; 
	
	//private Map<Thread,StackTraceElement[]> list;
	//private Set<Thread> keySet;
	//private Object [] tA;
	
	public MainThread()
		{
		super("MainThread");
		mF=new MainFrame();
		aSG=new AppSettingsGet();
		bSM=new BlueServerMonitor(this);
		bSM.start();
		}
	
	@Override
	public void run()
		{
		startServer();
		}
	
	public void externalStartServer()
		{
		startServer();
		}
	
	private void startServer() 
		{
		if(aSG.getSettings()!=null)
			{
			set=aSG.getSettings();
			
			if(sT==null)
				{
				sT=new SystemTrayManager(this);
				if(set.systemTrayEnabled)
					if(sT.trayAvailable())
						{
						sT.register();
						sT.disableMenuItem("Connect");
						sT.disableMenuItem("Disconnect");
						}
					else
						sT=null;
				}
			
			//System.out.println(set.connType);
			switch(set.connType)
				{
				case 1:
					{
					if(set.port!=null)
						{
						try
							{
							try
								{
								cPL=CommPortIdentifier.getPortIdentifier(set.port).open("Java Blue Remote Get Port", 5000);
								} 
							catch (PortInUseException e)
								{
								e.printStackTrace();
								}
							cPL.close();
							oTCP=new HandleTimeoutProcess(60000, sCS);
							oTCP.start();
							sCS=new StartCOMServer(this, cPL);
							sCS.start();
							} 
						catch (NoSuchPortException e)
							{
							e.printStackTrace();
							}
						}
					else
						{
						setupServer(0);
						}
					break;
					}
				case 2:
					{
					oTBC=new HandleTimeoutProcess(60000, sBCS);
					oTBC.start();
					sBCS=new StartBlueCoveServer(this);
					sBCS.start();
					break;
					}
				}
			}
		else
			{
			setupServer(0);
			}

		}
	
	public void setupServer(int setupCode)
		{
		mF.setVisible(true);
		sS=new SetupServerApp(this,mF,0);
		sS.start();
		}
	
	private void serverRunning(CommunicationManager cM)
		{
		sT.enableMenuItem("Disconnect");
		
		bSM.setServerStatus(true);
		serverR=new BlueServerReceiver(this,cM);
		serverR.start();
		status=new BlueServerClientStatus(serverR, bSM);
		status.start();
		}
	
	public void BlueCoveServerStatus(CommunicationManager cM)
		{
		cML=cM;
		if(oTBC!=null)
			oTBC.interrupt();
		System.out.println("CONNECTION ESTABLISHED");
		serverRunning=2;
		
		serverRunning(cML);
		}
	
	public void COMServerStatus(CommunicationManager cM)
		{
		cML=cM;
		if(oTCP!=null)
			oTCP.interrupt();
		System.out.println("CONNECTION ESTABLISHED");
		serverRunning=1;
		
		serverRunning(cML);
		}
	
	public void operationCancelled(TimeoutProcess tT)
		{
		System.out.println("Operation Failed "+tT.getProcessName());
		}
	
	public boolean isConnected()
		{
		return (serverRunning!=0);
		}

	public void connectTray()
		{
		System.out.println("C");
		}
	
	public void disconnectTray()
		{
		System.out.println("disC");
		}

	public void showServerTray()
		{
		System.out.println("showS");
		}
	
	public void clientStoppedResponding()
		{
		System.out.println("Client stopped responding");
		
		if(serverR!=null)
			{
			serverR.destroy();
			serverR=null;
			}
		
		if(status!=null)
			{
			status.destroy();
			status=null;
			}
		System.out.println("Restarting server");
		startServer();
		}
	
	public void destroy()
		{
				
		if(serverR!=null)
			{
			serverR.destroy();
			serverR=null;
			}

		if(status!=null)
			{
			status.destroy();
			status=null;
			}

		if(bSM!=null)
			{
			bSM.destroy();
			bSM=null;
			}
		
		if(sBCS!=null)
			{
			sBCS.destroy();
			sBCS=null;
			}
		
		if(sCS!=null)
			{
			sCS.destroy();
			sCS=null;
			}
		
		if(oTCP!=null && oTCP.isAlive())
			{
			oTCP.interrupt();
			oTCP=null;
			}
		
		if(oTBC!=null && oTBC.isAlive())
			{
			oTBC.interrupt();
			oTBC=null;
			}
		if(sT!=null)
			sT.destroy();
		
		/*while(true)
			{
			list=Thread.getAllStackTraces();
			keySet=list.keySet();
			tA=keySet.toArray();
			
			for(int i=0; i<tA.length; i++)
				System.out.println(((Thread) tA[i]).getName());
			
			try
				{
				sleep(1000);
				}
			catch (InterruptedException e)
				{
				e.printStackTrace();
				}
			
			System.out.println("-");
			//for(int i=0; i<tA.length; i++)
			//	System.out.println(tA.toString());
			}*/
		
		System.exit(0);
		}
	
	}
